﻿using SharpDX;
using SharpDX.Direct3D11;
using WorldRacing2.Material;

namespace Engine.Graphics.Shaders.Wr2Shaders
{
    public class ShaderbaseWr2 : ShaderBase
    {
        #region Private Fields

        private readonly SharpDX.Direct3D11.Buffer uvCoordinate1Buffer;
        private readonly SharpDX.Direct3D11.Buffer uvCoordinate2Buffer;
        private readonly SharpDX.Direct3D11.Buffer uvCoordinate3Buffer;
        private readonly BufferDescription uvCoordinateBufferDescription;
        private readonly Vector4[] uvMatrix1 = new Vector4[2];
        private readonly Vector4[] uvMatrix2 = new Vector4[2];
        private readonly Vector4[] uvMatrix3 = new Vector4[2];

        #endregion Private Fields

        #region Public Constructors

        public ShaderbaseWr2(Device renderDevice, ShaderManager shaderManager)
            : base(renderDevice, shaderManager)
        {
            // Buffer for uvTexture Matrices
            this.uvCoordinateBufferDescription = new BufferDescription()
            {
                BindFlags = BindFlags.ConstantBuffer,
                CpuAccessFlags = CpuAccessFlags.None,
                OptionFlags = ResourceOptionFlags.None,
                SizeInBytes = Utilities.SizeOf(uvMatrix1),
                Usage = ResourceUsage.Default,
                StructureByteStride = Utilities.SizeOf(uvMatrix1)
            };

            this.uvCoordinate1Buffer = SharpDX.Direct3D11.Buffer.Create(renderDevice, uvMatrix1, uvCoordinateBufferDescription);
            this.uvCoordinate2Buffer = SharpDX.Direct3D11.Buffer.Create(renderDevice, uvMatrix2, uvCoordinateBufferDescription);
            this.uvCoordinate3Buffer = SharpDX.Direct3D11.Buffer.Create(renderDevice, uvMatrix3, uvCoordinateBufferDescription);
        }

        #endregion Public Constructors

        #region Public Methods

        public void SetUvMatrix1(Wr2Material material)
        {
            if (ShaderBase.lastHashcodeMappingMatrix1 != material.Mappings1.CRC)
            {
                this.uvMatrix1[0] = material.GetMappings1A();
                this.uvMatrix1[1] = material.GetMappings1B();
                lock (this.Device.ImmediateContext)
                {
                    this.Device.ImmediateContext.UpdateSubresource(this.uvMatrix1, this.uvCoordinate1Buffer);
                    this.Device.ImmediateContext.VertexShader.SetConstantBuffer(1, this.uvCoordinate1Buffer);
                }
                ShaderBase.lastHashcodeMappingMatrix1 = material.Mappings1.CRC;
            }
        }

        public void SetUvMatrix2(Wr2Material material)
        {
            if (ShaderBase.lastHashcodeMappingMatrix2 != material.Mappings2.CRC)
            {
                this.uvMatrix2[0] = material.GetMappings2A();
                this.uvMatrix2[1] = material.GetMappings2B();
                lock (this.Device.ImmediateContext)
                {
                    base.Device.ImmediateContext.UpdateSubresource(this.uvMatrix2, this.uvCoordinate2Buffer);
                    this.Device.ImmediateContext.VertexShader.SetConstantBuffer(2, this.uvCoordinate2Buffer);
                }
                ShaderBase.lastHashcodeMappingMatrix2 = material.Mappings2.CRC;
            }
        }

        public void SetUvMatrix3(Wr2Material material)
        {
            if (ShaderBase.lastHashcodeMappingMatrix3 != material.Mappings3.CRC)
            {
                this.uvMatrix3[0] = material.GetMappings3A();
                this.uvMatrix3[1] = material.GetMappings3B();
                lock (this.Device.ImmediateContext)
                {
                    this.Device.ImmediateContext.UpdateSubresource(this.uvMatrix3, this.uvCoordinate3Buffer);
                    this.Device.ImmediateContext.VertexShader.SetConstantBuffer(3, this.uvCoordinate3Buffer);
                }
                ShaderBase.lastHashcodeMappingMatrix3 = material.Mappings3.CRC;
            }
        }

        #endregion Public Methods
    }
}